﻿/* ----------------------------------------------------------------------------
 * Copyright (c) Rob Ashton 2009
 *
 * This source code is subject to terms and conditions of the Microsoft Public 
 * License (Ms-PL).
 * 
 * By using this source code in any fashion, you are agreeing to be bound 
 * by the terms of the Microsoft Public License.
 * 
 * To request a copy of the Microsoft Public License, send a request by email
 * to license@mvcex.com
 *
 * This notice must not be removed from this software.
 * ---------------------------------------------------------------------------- */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml.Serialization;
using MvcEx.Configuration;
using MvcEx.Controllers;
using MvcEx.Views;
using MvcEx.Theming;
using System.Web.Mvc;

namespace MvcEx
{
    /// <summary>
    ///
    /// </summary>
    public sealed class MvcExApplication : IMvcExApplication
    {
        private MvcExApplicationConfiguration mConfiguration;
        private MvcExControllerFactory mControllerFactory;
        private MvcExViewEngine mViewEngine;
        private IMvcExApplicationConfigurationSelector mConfigSelector;

        private MvcExApplication() {}

        public static IMvcExApplication Create(String baseDir)
        {
            // Create the application
            MvcExApplication application = new MvcExApplication();

            // Create the configuration
            application.mConfiguration = MvcExApplicationConfiguration.Load(baseDir);

            // Set up the theme provider
            MvcExThemeSystem.ThemeSelector = new MvcExApplicationThemeSelector(application);

            // Set up the controller factory
            application.mControllerFactory = new MvcExControllerFactory(
                new MvcExApplicationControllerBuilderSelector(application)
                );

            // Set up the view engine
            application.mViewEngine = new MvcExViewEngine(
                new MvcExApplicationViewEngineConfigurationSelector(application)
                );

            // Create the default configuration selector (choose the first in the list)
            String defaultId = string.Empty;
            if (application.mConfiguration.Configurations.Length > 0)
            {
                defaultId = application.mConfiguration.Configurations[0].Id;
            }
            application.SetConfigurationSelector(
                new MvcExDefaultApplicationConfigurationSelector()
                {
                     DefaultConfiguration = defaultId
                });

            // Register the controller factory + view engine
            ControllerBuilder.Current.SetControllerFactory(application.mControllerFactory);
            ViewEngines.Engines.Clear();
            ViewEngines.Engines.Add(application.mViewEngine);

            // Return the application
            return application;
        }

        #region IMvcExApplication Members

        public event EventHandler ConfigurationChanged;

        public MvcExControllerFactory ControllerFactory
        {
            get
            {
                return mControllerFactory;
            }
        }

        public MvcExViewEngine ViewEngine
        {
            get
            {
                return mViewEngine;
            }
        }

        public MvcExConfiguration GetActiveConfiguration()
        {
            String configId = mConfigSelector.GetActiveConfigurationId();
            return mConfiguration.Configurations.Where(x => x.Id == configId).SingleOrDefault();
        }

        public MvcExModule GetModuleById(string id)
        {
            return mConfiguration.GetModuleById(id);
        }

        public void Reload()
        {
            mConfiguration.ResetConfiguration();
            var ev = this.ConfigurationChanged;
            if (ev != null)
            {
                ev(this, EventArgs.Empty);
            }
        }

        public void SetConfigurationSelector(IMvcExApplicationConfigurationSelector configSelector)
        {
            mConfigSelector = configSelector;
        }
                
        public IEnumerable<MvcExConfiguration> GetConfigurations()
        {
            return mConfiguration.Configurations;
        }

        #endregion
    }
}
